package com.ruoyi.project.app.interfaces;

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.security.*;

import java.awt.image.BufferedImage;
import java.io.*;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.*;

import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;

public interface PdfToolInterface {

    /**
     * 生成某页pdf
     *
     * @param templatePdfPath 模板pdf路径
     * @param generatePdfPath 生成pdf路径
     * @param data            数据
     */
    default void generatePdf(String templatePdfPath, String generatePdfPath, Map<String, String> data, int page) {
        Document doc = null;
        OutputStream fos = null;
        ByteArrayOutputStream bos = null;
        try {
            doc = new Document();
            fos = new FileOutputStream(generatePdfPath);
            bos = new ByteArrayOutputStream();
            PdfReader reader = new PdfReader(templatePdfPath);
            /* 将要生成的目标PDF文件名称 */
            PdfStamper ps = new PdfStamper(reader, bos);
            /* 使用中文字体 */
            ArrayList<BaseFont> fontList = new ArrayList<>();
            fontList.add(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));
            /* 取出报表模板中的所有字段 */
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            // 填充字段
            Map<String, AcroFields.Item> formFields = fields.getFields();
            for (String itemKey : formFields.keySet()) {
                System.out.println("itemKey=" + itemKey + "\t\t\titemValue=" + data.get(itemKey));
                fields.setField(itemKey, data.get(itemKey));
            }
            /* 必须要调用这个，否则文档不会生成的  如果为false那么生成的PDF文件还能编辑，一定要设为true*/
            ps.setFormFlattening(true);
            ps.close();

            PdfCopy copy = new PdfCopy(doc, fos);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), page);
            copy.addPage(importPage);

            fos.write(bos.toByteArray());
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (doc != null) {
                try {
                    doc.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生成pdf
     *
     * @param templatePdfPath 模板pdf路径
     * @param generatePdfPath 生成pdf路径
     * @param data            数据
     */
    default void generatePdf(String templatePdfPath, String generatePdfPath, Map<String, String> data) {
        OutputStream fos = null;
        ByteArrayOutputStream bos = null;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            bos = new ByteArrayOutputStream();
            /* 将要生成的目标PDF文件名称 */
            PdfStamper ps = new PdfStamper(reader, bos);
            /* 使用中文字体 */
            ArrayList<BaseFont> fontList = new ArrayList<>();
            fontList.add(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));
            /* 取出报表模板中的所有字段 */
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            // 填充字段
            Map<String, AcroFields.Item> formFields = fields.getFields();
            for (String itemKey : formFields.keySet()) {
                System.out.println("itemKey=" + itemKey + "\t\t\titemValue=" + data.get(itemKey));
                fields.setField(itemKey, data.get(itemKey));
            }
            /* 必须要调用这个，否则文档不会生成的  如果为false那么生成的PDF文件还能编辑，一定要设为true*/
            ps.setFormFlattening(true);
            ps.close();
            fos = new FileOutputStream(generatePdfPath);
            fos.write(bos.toByteArray());
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生成pdf
     *
     * @param templatePdfPath 模板pdf路径
     * @param imagePath       生成图片路径
     * @param data            数据
     */
    default void generateImage(String templatePdfPath, String imagePath, Map<String, String> data) {
        OutputStream fos = null;
        ByteArrayOutputStream bos = null;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            bos = new ByteArrayOutputStream();
            /* 将要生成的目标PDF文件名称 */
            PdfStamper ps = new PdfStamper(reader, bos);
            /* 使用中文字体 */
            ArrayList<BaseFont> fontList = new ArrayList<>();
            fontList.add(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));
            /* 取出报表模板中的所有字段 */
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            // 填充字段
            Map<String, AcroFields.Item> formFields = fields.getFields();
            for (String itemKey : formFields.keySet()) {
                System.out.println("itemKey=" + itemKey + "\t\t\titemValue=" + data.get(itemKey));
                fields.setField(itemKey, data.get(itemKey));
            }
            /* 必须要调用这个，否则文档不会生成的  如果为false那么生成的PDF文件还能编辑，一定要设为true*/
            ps.setFormFlattening(true);
            ps.close();

            fos = new FileOutputStream(imagePath);
            fos.write(bos.toByteArray());
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @param password     秘钥密码
     * @param keyStorePath 秘钥文件路径
     * @param signPdfSrc   签名的PDF文件
     * @param signImage    签名图片文件
     * @param x            x坐标
     * @param y            y坐标
     * @return
     */
    default byte[] sign(String password, String keyStorePath, String signPdfSrc, String signImage, float x, float y) {
        File signPdfSrcFile = new File(signPdfSrc);
        PdfReader reader = null;
        ByteArrayOutputStream signPDFData = null;
        PdfStamper stp = null;
        FileInputStream fos = null;
        try {
            BouncyCastleProvider provider = new BouncyCastleProvider();
            Security.addProvider(provider);
            KeyStore ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());
            fos = new FileInputStream(keyStorePath);
            // 私钥密码 为Pkcs生成证书是的私钥密码 123456
            ks.load(fos, password.toCharArray());
            String alias = (String) ks.aliases().nextElement();
            PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());
            Certificate[] chain = ks.getCertificateChain(alias);
            reader = new PdfReader(signPdfSrc);
            signPDFData = new ByteArrayOutputStream();
            // 临时pdf文件
            File temp = new File(signPdfSrcFile.getParent(), System.currentTimeMillis() + ".pdf");
            stp = PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);
            stp.setFullCompression();
            PdfSignatureAppearance sap = stp.getSignatureAppearance();
            sap.setReason("数字签名，不可改变");
            // 使用png格式透明图片
            Image image = Image.getInstance(signImage);
            sap.setImageScale(0);
            sap.setSignatureGraphic(image);
            sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
            // 是对应x轴和y轴坐标
            sap.setVisibleSignature(new Rectangle(x, y, x + 185, y + 68), 1,
                    UUID.randomUUID().toString().replaceAll("-", ""));
            stp.getWriter().setCompressionLevel(5);
            ExternalDigest digest = new BouncyCastleDigest();
            ExternalSignature signature = new PrivateKeySignature(key, DigestAlgorithms.SHA512, provider.getName());
            MakeSignature.signDetached(sap, digest, signature, chain, null, null, null, 0, MakeSignature.CryptoStandard.CADES);
            stp.close();
            reader.close();
            return signPDFData.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (signPDFData != null) {
                try {
                    signPDFData.close();
                } catch (Exception e) {
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                }
            }
        }
        return null;
    }

//    default void pdfToImags(String filePath, String savePath) throws IOException {
//        String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1,
//                filePath.length());
//        fileName = fileName.substring(0, fileName.lastIndexOf("."));
//        File file = null;
//        InputStream in = null;
//        PDPageTree pages = null;
//        int buff = 1024 * 1024;
//        PDDocument pdDocument = null;
//        try {
//            file = new File(filePath);
//            if (file.exists()) {
//                in = new BufferedInputStream(new FileInputStream(filePath),
//                        buff);
//                PDFParser parser = new PDFParser(in);
//                parser.parse();
//                pdDocument = parser.getPDDocument();
//                pages = pdDocument.getDocumentCatalog().getPages();
//                for (int i = 0; i < pages.size(); i++) {
//                    PDPage page = (PDPage) pages.get(i);
//                    BufferedImage img_temp = page.convertToImage();
//                    Iterator iterator = ImageIO
//                            .getImageWritersBySuffix(IMG_TYPE_JPG);
//                    ImageWriter writer = (ImageWriter) iterator.next();
//                    ImageOutputStream imageOut = ImageIO
//                            .createImageOutputStream(new FileOutputStream(
//                                    new File(savePath + "\\" + fileName + "-" + i + ".jpg")));
//                    writer.setOutput(imageOut);
//                    writer.write(new IIOImage(img_temp, null, null));
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            if (pdDocument != null) {
//                pdDocument.close();
//            }
//
//        }
//    }
}
